<style lang="scss">

@mixin reset() {
  line-height: 1.15 ;
}

// xy-text 的表单属性
xy-text[type-field] {
  background-color: var(--el-color-primary-light-1);
  padding-left: 5px;
  padding-right: 5px;
  color: #fff;
  border-radius: 2px;
  height: 30px;
  line-height: 30px;
  margin-left: 3px;
  margin-right: 3px;
  &::after {
    background-color: transparent;
    right: -3px;
  }
  //user-select: none;
}

// xy-text 的全局变量
xy-text[data-global-var] {
  background-color: var(--el-color-info);
  padding-left: 5px;
  padding-right: 5px;
  color: #fff;
  border-radius: 2px;
  height: 30px;
  line-height: 30px;
  margin-left: 3px;
  margin-right: 3px;
  &::after {
    background-color: transparent;
    right: -3px;
  }
  //user-select: none;
}

.z-drag-xml {

  .jv-container {
    @include reset();
  }
  .z-dragxml-com {
    @include reset();
  }
  .debug-tool {
    @include reset();
  }



  $menu-trigger-height: 50px;
  .menu-control {
    border-right: var(--el-border-base);
    &-trigger {
      height: $menu-trigger-height;
      display: flex;
      align-items: center;
      justify-content: center;
      cursor: pointer;
    }
  }

  .el-menu-item > * {
    text-align: center;
  }


  .menu-control-trigger {
    display: none;
  }

  .zdragxml__control-button {
    background-color: var(--el-color-primary);
    color: #fff;
    appearance: none;
    border: none;
    border-radius: 2px;
    &:hover {
      filter: brightness(105%);
    }
  }

  .zdragxml__del-button {
    background-color: var(--el-color-danger);
    margin-left: 10px;
  }


  .z-drag-layout--custom-layout {
    float: left;
    &:last-child {
      float: none;
    }
  }
}

.z-drag-xml--half-full {
  .action-column {
    position: fixed;
    left: 0;
    z-index: 222;
    max-width: none;
    width: 400px;
    pointer-events: none;
    //padding: 120px;
    .el-menu {
      pointer-events: auto;
      //text-align: center;
    }

    .el-menu + div {
      pointer-events: auto;
      transform: translateX(-100%);
      z-index: -1;
      background: #fff;
      transition: transform 1s ease;
    }
  }
  .action-column + * {
    margin-left: 70px;
  }
  .menu-control-trigger {
    display: flex;
  }

  .action-column--show-menu {
    .el-menu + div {
      pointer-events: auto;
      transform: translateX(0);
      z-index: 1;
      transition: transform 1s ease, z-index 1s ease 1s;
    }
  }

  .action-column ~ * {
    //transition: transform 1s ease;
  }
}

//.z-drag-xml--show-menu {
//  .action-column ~ * {
//    transform: translateX(410px);
//    //margin-left: 410px;
//  }
//}

.z-drag-xml__actions {
  h3 {
    margin-bottom: 0;
  }
  .el-form-item {
    margin-bottom: 10px;
  }
}

.z-drag-xml__panel-header {
  line-height: 1.5;
  --z-dragxml-label--name-fz: 14px
}

.custom-tree {
  :deep(.el-tree-node__content) {
    height: initial;
  }
  .el-tree-node__content {
    height: initial;
  }
}

.custom-tree-node {
  width: 100%;
  box-sizing: border-box;
  height: 36px;
}

[z-drag-start] {
  border-bottom: 1px dashed transparent;
  //&:hover {
  //  border-bottom-color: #0d84ff;
  //}
}
.form-first-item {
  height: 3px;
  padding: 1px;
  border: none;
  //pointer-events: none;
}
[current-to-move] {
   /*background-color: #0d84ff;*/
  border: 1px dashed transparent;
  /*border-bottom: 2px solid;*/
  /*border-bottom-color: #0d84ff;*/
  pointer-events: none;
  position: relative;
  > * {
    pointer-events: all;
  }
  > button {
    margin-right: 10px;
  }
  > [actions] {
    position: absolute;
    //transform: translate(-100%);
    left: 0;
    top: 0;
    pointer-events: all;
    font-size: 12px;
    z-index: 1111111;
  }
  .inspect-label {
    position: absolute;
    left: 0;
    top: 0;
    transform: translateY(-120%);
    //color: #4099f8;
  }
}
[current-to-move=rect] {
  border-color:  var(--el-color-primary);
}
[current-to-move=line] {
  //border-color:  var(--el-color-primary;
  border-bottom-color:  var(--el-color-primary);
}
.debug-tool2 {
  [current-to-move=line] {
    border-bottom-color:  var(--el-color-primary);
  }
}

.debug-tool3 {
  [current-to-move] {
    border-color:  var(--el-color-primary);
    border-width: 1px;
    border-style: solid;
    > button {
      display: none;
    }
    .inspect-label {
      display: none;
    }
  }
}

.el-radio-button__original-radio:checked + .el-radio-button__inner {
  fill: var(--el-radio-button-checked-font-color, var(--el-color-white));
}

//.menu-control__panel {
//  position: absolute;
//  left: 55px;
//  width: 450px;
//  z-index: 1111;
//  background: #fff;
//}

$play_media: (
mobile: 375px,
);
.playground {
  min-height: 500px;
  background-color: rgb(255, 255, 255);
  border: 1px solid rgb(238, 238, 238);
  margin: 0 auto;
  &[type=mobile] {
    width: map-get($play_media, mobile);
  }

}

.el-tree-node__content>.el-tree-node__expand-icon {
  width: 0;
}

@media screen and (max-width:1200px) {
  $list: 270px,340px;
  .z-drag-xml__column:nth-child(1) {
    width: #{nth($list, 1)};
  }
  .z-drag-xml__column:nth-child(2) {
    width: calc(100% - #{nth($list, 1)} - #{nth($list, 2)});
    overflow: auto;
  }
  .z-drag-xml__column:nth-child(3) {
    width: #{nth($list, 2)};
  }
  .z-drag-xml__tplComponent {
    //.g-list-group-item {
    //  width: 100%;
    //  max-width: none;
    //  flex: none;
    //}
    .g-list-group-item:nth-child(2n+1) .g-list-group-item__element {
      margin-left: 8px;
    }
    .g-list-group-item__element {
      width: 100px;
      padding: 0;
      padding-left: 5px;
    }
  }
  .z_dragxml__table_con {
    width: 210px;
    .el-table td.el-table__cell div {
      padding-left: 2px;
      padding-right: 2px;
    }
    .el-button + .el-button {
      margin-left: 5px;
    }
  }
  .z-drag-xml__menu {
    width: 44px;
    .el-menu-item {
      padding: 0 !important;
    }
    .el-tooltip__trigger {
      padding: 0 !important;
    }
  }

}

@media screen and (min-width:1200px) {
  $list: 350px, 430px;
  .z-drag-xml__column:nth-child(1) {
    width: #{nth($list, 1)};
  }
  .z-drag-xml__column:nth-child(2) {
    width: calc(100% - #{nth($list, 1)} - #{nth($list, 2)});
  }
  .z-drag-xml__column:nth-child(3) {
    width: #{nth($list, 2)};
  }
  .z_dragxml__table_con {
    width: 270px;
  }
}

</style>

<template>
  <div class="z-drag-xml"
       @mouseleave="onMouseLeave"
       @mousedown="onMouseDown"
       :class=" {['z-drag-xml--' + toolState.viewMode]: 1, ['z-drag-xml--show-menu']: toolState.showMenu}" :id="ELE_ID" @mousemove="onMouseMove" >
<!--    {{state}}-->
    <el-row :style="{height: toolState.toolbarHeight}" justify="space-between" align="middle">
      <el-col :span="toolState.toolSpans[0]"><slot name="title"></slot>
        <slot-com :defs="form_slot_content" :attrs="{}" name="z_dragxml_title_after"  :binds="{ctx: exportCtx}"></slot-com>
      </el-col>
      <el-col :span="toolState.toolSpans[1]">
        <el-row  justify="center">
          <el-radio-group size="small" v-model="toolState.type">
            <el-radio-button label="mobile">
              <svg t="1643001653094" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12219" width="16" height="16"><path d="M748.992 38.048 275.008 38.048c-37.408 0-67.68 30.304-67.68 67.68l0 812.512c0 37.408 30.304 67.68 67.68 67.68l473.984 0c37.408 0 67.68-30.304 67.68-67.68L816.672 105.728C816.672 68.352 786.4 38.048 748.992 38.048zM275.008 71.904l473.984 0c18.656 0 33.824 15.168 33.824 33.824l0 710.944L241.184 816.672 241.184 105.728C241.184 87.072 256.352 71.904 275.008 71.904zM748.992 952.096 275.008 952.096c-18.656 0-33.824-15.168-33.824-33.824L241.184 833.6l541.632 0 0 84.672C782.816 936.928 767.648 952.096 748.992 952.096z" p-id="12220"></path><path d="M461.216 884.416l101.568 0 0 16.928-101.568 0 0-16.928Z" p-id="12221"></path></svg>
            </el-radio-button>
            <el-radio-button label="responsive">
              <svg t="1643001807219" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13875" width="16" height="16"><path d="M919.565463 121.942283 104.433514 121.942283c-22.036899 0-40.066531 18.029632-40.066531 40.066531L64.366983 682.937161c0 22.036899 18.029632 40.066531 40.066531 40.066531l345.360725 0-10.544147 107.886149L250.5248 830.889841l-10.544147 71.167876 544.03767 0-11.598152-71.167876L584.748884 830.889841l-10.544147-107.886149 345.360725 0c22.036899 0 40.066531-18.029632 40.066531-40.066531L959.631994 162.008814C959.633017 139.971915 941.602362 121.942283 919.565463 121.942283zM935.467641 659.734716 88.531336 659.734716 88.531336 178.113607l846.936305 0L935.467641 659.734716z" p-id="13876"></path></svg>
             </el-radio-button>
          </el-radio-group>
        </el-row>
      </el-col>
      <el-col :span="toolState.toolSpans[2]">
        <el-row style="flex: 1" justify="end" align="middle">
          <slot-com :defs="form_slot_content" :attrs="{}" name="z_dragxml_action_before" :binds="{ctx: exportCtx}"></slot-com>
<!--          <z-easy-modal title="数据展示" :buttonAttr="{size: 'small'}" :model-attr="{width: '60vw'}">-->
<!--            <template #button-content>打开数据展示</template>-->
<!--            <template #default>-->
<!--              <el-button class="a-space-mb-10" @click="downloadJSON(getZProps())">下载json5</el-button>-->
<!--              <v-json-viewer-->
<!--                  :expand-depth=10  :expanded="true"-->
<!--                  boxed-->
<!--                  :value="getZProps(false)"></v-json-viewer>-->
<!--            </template>-->
<!--          </z-easy-modal>-->

          <el-button type="small" @click="downloadJSON(getZProps())">下载属性</el-button>
          <z-export-dialog class="a-space-ml-10"
                           style="display: flex; align-items: center"
                           :button-attr="{ size:'small'}"
                           @exported="exportFile"></z-export-dialog>
          <el-button class="a-space-ml-10"
                     size="small" @click="importFile">导入</el-button>
        </el-row>
      </el-col>

    </el-row>
    <el-row >
      <div class="z-drag-xml__column action-column"
              :class="{['action-column--show-menu']: toolState.showMenu}"
              >
        <el-row style="min-height: 30vh">
          <el-menu
              :default-active="toolState.defaultIndex"
              class="z-drag-xml__menu"
              :collapse="true"
              @select="handleMenuSelect"
          >
            <el-menu-item index="1">
              <el-icon><document /></el-icon>
              <template #title>大纲树</template>
            </el-menu-item>
            <el-menu-item index="2">
              <el-icon><icon-menu /></el-icon>
              <template #title>组件库</template>
            </el-menu-item>
            <el-menu-item index="3">
              <el-icon><files /></el-icon>
              <template #title>模板</template>
            </el-menu-item>

            <div class="menu-control-trigger"
                 @click="toggleShowMenu">
              <svg t="1642656399741" class="menu-control-icon" v-if="toolState.showMenu"
                   viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
                   p-id="2139" width="16" height="16"><path d="M874.666667 800H149.333333c-17.066667 0-32 14.933333-32 32s14.933333 32 32 32h725.333334c17.066667 0 32-14.933333 32-32s-14.933333-32-32-32zM149.333333 224h725.333334c17.066667 0 32-14.933333 32-32s-14.933333-32-32-32H149.333333c-17.066667 0-32 14.933333-32 32s14.933333 32 32 32zM341.333333 480c-17.066667 0-32 14.933333-32 32s14.933333 32 32 32h512c17.066667 0 32-14.933333 32-32s-14.933333-32-32-32H341.333333z" p-id="2140"></path><path d="M275.2 684.8c6.4 6.4 14.933333 8.533333 23.466667 8.533333s17.066667-2.133333 23.466666-8.533333c12.8-12.8 12.8-32 0-44.8l-128-128 125.866667-125.866667c12.8-12.8 12.8-32 0-44.8-12.8-12.8-32-12.8-44.8 0l-149.333333 149.333334c-12.8 12.8-12.8 32 0 44.8l149.333333 149.333333z" p-id="2141"></path></svg>
              <svg t="1642656420166"  class="menu-control-icon" v-if="!toolState.showMenu"
                   viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
                   p-id="2383" width="16" height="16"><path d="M874.666667 800H149.333333c-17.066667 0-32 14.933333-32 32s14.933333 32 32 32h725.333334c17.066667 0 32-14.933333 32-32s-14.933333-32-32-32zM149.333333 224h725.333334c17.066667 0 32-14.933333 32-32s-14.933333-32-32-32H149.333333c-17.066667 0-32 14.933333-32 32s14.933333 32 32 32zM149.333333 544h512c17.066667 0 32-14.933333 32-32s-14.933333-32-32-32H149.333333c-17.066667 0-32 14.933333-32 32s14.933333 32 32 32z" p-id="2384"></path><path d="M748.8 339.2c-12.8-12.8-32-12.8-44.8 0-12.8 12.8-12.8 32 0 44.8l125.866667 125.866667-125.866667 125.866666c-12.8 12.8-12.8 32 0 44.8 6.4 6.4 14.933333 8.533333 23.466667 8.533334s17.066667-2.133333 23.466666-8.533334l149.333334-149.333333c12.8-12.8 12.8-32 0-44.8l-151.466667-147.2z" p-id="2385"></path></svg>
            </div>
          </el-menu>

          <div style="flex: 1;" class="menu-control__panel">
            <el-scrollbar :height="toolState.menuConHeight" v-show="toolState.activeIndex === '1'" >
              <el-tree default-expand-all
                       class="custom-tree"
                       :data="treeState.data"
                       :props="treeState.defaultProps"
                       node-key="id"
                       @node-click="handleTreeNodeClick"
                       :expand-on-click-node="false"
                       :ref="initTreeRef"
              >
                <template #default="{ node, data }">
                  <el-row justify="space-between"
                          class="custom-tree-node"

                  >
                    <el-row align="middle">
                      <template v-if="data.label_xml"><div v-html="data.label_xml"></div></template>
                      <template v-if="!data.label_xml">{{data.label}}</template>
                      <div hidden>{{data.tree_id}}</div>
                    </el-row>
                    <el-row align="middle"
                            v-if="!data.NOT_ACTION"
                    >
                      <el-button size="small"
                                 type="danger"
                                 @click.stop="removeTreeNode(node, data)"> 删除 </el-button>
                    </el-row>
                  </el-row>
                </template>
              </el-tree>
            </el-scrollbar>

            <el-scrollbar :height="toolState.menuConHeight" v-show="toolState.activeIndex === '2'">
              <!--              {{treeState.tplComponents}}-->
              <div class="z-drag-xml__tplComponent"
                   v-for="(components, index) in treeState.tplComponents">
                <!--                {{index}}-->
                <h3
                    class="a-space-ph-10"
                    style="line-height: 1; margin-top: 0; margin-bottom: 10px">{{treeState.tplComponents[index].label}}</h3>
                <draggable
                    class="dragArea g-list-group"
                    v-model="treeState.tplComponents[index].components"
                    @start="onDropStart"
                    @end="onDropEnd"
                    :group="{ name: toolState.group, pull: 'clone', put: false }"
                    :sort="false"
                    item-key="id"
                    tag="el-row"
                    style="align-items: flex-start; flex-wrap: wrap;"
                >
                  <template #item="{element}">
                    <el-col class="g-list-group-item"
                            :class="list1ItemCls(element)"
                            :span="12"
                            :data-name="element.name"
                            :data-column-max="element.columnMax"
                            :data-darg-exp="element.exp"
                            v-if="checkIsShowMenuItem(element)"
                    > <div
                        class="g-list-group-item__element" v-html="element.label"></div></el-col>
                  </template>
                </draggable>
              </div>
            </el-scrollbar>

            <el-scrollbar :height="toolState.menuConHeight" v-show="toolState.activeIndex === '3'">
              <!--              {{treeState.tplComponents}}-->
              <slot-com :defs="form_slot_content" :attrs="{}"
                        name="z_dragxml_tpl_panel" :binds="{ctx: exportCtx}"></slot-com>
            </el-scrollbar>
          </div>
        </el-row>
      </div>
      <div class="z-drag-xml__column z-drag-xml__column-playground">
        <el-scrollbar
        :max-height="toolState.maxCanvasHeight"
        :ref="initScrollRef"
        >
          <div :id="playgroundId"
               class="playground"
               :type="toolState.type"
               data-index="-1"
               @dragover="onDragMove"
          >
            <div style="height: 3px; margin-bottom: 3px" z-drag-start>&nbsp;</div>
            <z-layout-init
                z-uuid-init-str="1"
                :z-uuid="item.uuid"
                :uuid="item.uuid"
                v-for="(item, index) in state.layouts"
                :key="item.uuid"
                :column="1"
                :ref="initZlayoutInitRef(item)"
                :column-max="item.columnMax"
                :drag-enter="onZLayoutInitDragEnter"
                @clear-index="onClearIndex"
                @column-max-err="onClearIndex"
                @changed="onChangedLayout(item, $event)"
                @drag-end="onDragEnd(item, $event)"
                :style="item.style"
                :class="item.class"
            ></z-layout-init>
          </div>
        </el-scrollbar>
      </div>
      <div class="z-drag-xml__column">
        <div style="padding-left: 10px; box-sizing: border-box;">
          <template v-if="treeState.current && treeState.current.uuid && treeState.showCurrent">
            <div class="z-drag-xml__panel-header"
                 :style="{height: toolState.panelHeaderHeight}"
                 v-html="treeState.current.com_xml"></div>
            <div class="z-drag-xml__actions app-scroller"  :class="getTreeStateCurrentCls()"
                 :height="toolState.scrollBarHeight"
                 :style="{height: toolState.scrollBarHeight }"
            >
              <z-http-com :resolve-config="resolveConfig"
                          @http:model:change="onModelChange"
                          @select-list="onSelectList"
                          @select-checked="onSelectChecked"
              ></z-http-com>
            </div>
          </template>
        </div>
<!--        {{treeState.current}}-->
      </div>
    </el-row>
    <div class="debug-tool debug-tool1" :id="testId1"></div>
    <div class="debug-tool debug-tool2" :id="testId2"></div>
    <div class="debug-tool debug-tool3" :id="testId3"></div>
    <div class="debug-tool" :id="id" v-for="id in TEST_IDS"></div>
  </div>
</template>

<script>
import {inject, nextTick, onMounted, provide, reactive, toRaw} from "vue";
import draggable from 'vuedraggable'
import JsxRender from "@/components/jsxrender.vue";
import RenderDom from "@/components/renderDom.vue";
import ZLayoutInit from "@/plugins/z-frame/components/ZLayoutInit.vue";
import {DATA_LAYOUT_ITEM_UUID_KEY, DATA_LAYOUT_UUID_KEY} from "@/vars";
import Sortable from 'sortablejs';
import mitt from "mitt";
import ZHttpCom from "@/plugins/z-frame/components/ZHttpCom.vue";
import {createCusWidgetEditorConfig} from "@/plugins/form-render/components/CusWidgetEditor/createConfig";
import ZCommonAttrs from "@/plugins/z-frame/components/ZCommonAttrs.vue";
import {QuickBooleanWithNull, setPROPS} from "@/hooks/props";
import ZEasyModal from "@/plugins/z-frame/components/ZEasyModal.vue";
import {initTplComponents} from "@/plugins/z-frame/components/ZDragXml/tplComponents";
import deepMerge from 'deepmerge'

import {Document, Files, Location, Menu as IconMenu, Setting,} from '@element-plus/icons'
import ZExportDialog from "@/plugins/z-frame/components/ZEchartsEasy/ZExportDialog.vue";
import {createZdragXmlToolState} from "@/plugins/z-frame/components/ZDragXml/toolState";

const ZRAGXML_VARS = {
  wrap_start_tag: 'z-grid',
  wrap_end_tag: 'z-grid',
  grid_item_start_tag: 'z-grid-item',
  grid_item_end_tag: 'z-grid-item',
}

/**
 * 获取真实的com def
 * @param com
 * @returns {null|*}
 */
function getTrueComDef(com) {
  // if (com.DRAG_LABEL_XML) {
  //   return res
  // }
  if (com && com.name) {
    return CustomVueComponent.resolve(com.name)
  }
  return null
}
// con_uuid 就是z-layout-init 在layoutRefMap里key
export default {
  name: 'ZDragXml',
  components: {
    ZExportDialog,
    ZEasyModal,
    Files,
    ZCommonAttrs,
    ZHttpCom,
    ZLayoutInit,
    RenderDom,
    JsxRender,
    draggable,
    Location,
    Document,
    IconMenu,
    Setting,
  },
  props: {
    insVars: {
      type: Array,
      default() {
        return []
      }
    },
    form_slot_content: null
  },
  setup(props, ctx) {

    let app = getApp();
    let imeVarsFunName = 'ime__' + ZY.rid(10)


    let bindingRect = null
    onMounted(() => {
      let instance = document.getElementById(ELE_ID)
      bindingRect = instance.getBoundingClientRect()
      // console.log(bindingRect)
    })


    let _currentBuild = null;
    let _currentBuildV2 = null;

    const Z_UUID_KEY = 'z-uuid'
    const Z_INIT_UUID_KEY = 'z-init-uuid'
    const PLAY_ID = 'playground__' + ZY.rid(6)
    const TEST1_ID = 'test1__' + ZY.rid(6)
    const TEST2_ID = 'test2__' + ZY.rid(6)
    const TEST3_ID = 'test3__' + ZY.rid(6)
    const ELE_ID = 'zdragxml__' + ZY.rid(6)

    const TEST_IDS = [
      'sdsds__' + ZY.rid(6)
    ]

    let lodash = ZY.lodash;
    let JSON5 = ZY.JSON5;
    let originalEvent = {
    }
    let currentToTarget = null
    let currentToMove = null
    let state = reactive({
      components: [],
      filterList: '',
      isDragging: false,
      disableDrag: false,
      currentDragItem: {},
      cachedGridItem: null,
      // tree: [],
      layouts: [],
      layoutRefMap: {},
      layoutRefs: {},
      uuids: [],
      comMemo: {}
    })

    let {toolState, toggleShowMenu, isNeedToggleMenu} = createZdragXmlToolState()

    const handleMenuSelect = (key) => {
      // console.log(key, keyPath)
      toolState.activeIndex =  key
      if (isNeedToggleMenu()) {
        toggleShowMenu()
      }
    }
    const handleMenuClose = (key, keyPath) => {
      console.log('handleMenuClose', key, keyPath)
    }

    async function downloadJSON(data) {
      let d = ZY.JSON5.parse(ZY.JSON5.stringify(data))
      await ZY_EXT.saveJSONFile({
        data: d,
        prefix: 'z_drag_form__'
      })
    }

    function clearTestToolsInspect() {
      testTools.forEach(t => {
        t()
      })
    }

    // 存储每个组件memo
    let memos = new Map()
    let memoDatas = new Map()
    let dragConfig = new Map()
    let emitter = mitt()
    let DRAG_EVENTS = {
      CHANGED: 'CHANGED',
      FORM_CONFIG: 'FORM_CONFIG',
      OTHER: 'OTHER',
      CHANGED1: 'CHANGED',
      CHANGED2: 'CHANGED',
      CHANGED3: 'CHANGED',
      HIGHLIGHT: 'HIGHLIGHT',
    }
    let DRAG_CONTEXT = new Map()
    let DRAG_INSTANSE = {
      EVENTS:DRAG_EVENTS,
      imeVarsFunName,
      dragConfig,
      setMemosCtx(uuid, ctx) {
        // console.log('setMemoCtx', uuid, ctx)
        memos.set(uuid, ctx)
        if (memoDatas.has(uuid)) {
          ctx.fromMemo(memoDatas.get(uuid))
        }
      },
      setConfig(key, value) {
        dragConfig.set(key, value)
        emitter.emit(DRAG_EVENTS.CHANGED, {
          key,
          value,
        })
      },
      getConfig(key) {
        return dragConfig.get(key)
      },
      updateConfig(key, cb, init) {
        let o = dragConfig.get(key)
        if (!o) {
          o = {
            ins: {
            },
            common: {}
          }
          if (init) {
            init(o)
          }
        } else {
          if (cb) {
            cb(o)
          }
        }
        dragConfig.set(key, o)
      },
      clearAllConfig(key) {
        return dragConfig.clear()
      },
      /**
       *
       * @returns {Map<any, any>}
       */
      getAllConfig() {
        return dragConfig
      },
      delConfig(key) {
        dragConfig.delete(key)
      },
      hasConfig(key) {
        return dragConfig.has(key)
      },
      register(key, value) {
        DRAG_CONTEXT.set(key, value)
        // console.log('register', state.comMemo, key, value)
        if (state.comMemo && state.comMemo[key] ) {
          if (value && value.fromMemo) {
            value.fromMemo(state.comMemo[key] )
          }
          Reflect.deleteProperty(state.comMemo, key)
        } else {
          if (value && value.noMemo) {
            value.noMemo( )
          }
        }
        // if ( value && value.onRegister) {
        //   value.onRegister(state.comMemo[key])
        // }
      },
      unRegister(key) {
        DRAG_CONTEXT.delete(key)
      },
      /**
       * 同 getRegisterCtx
       * @deprecated
       * @param key
       * @returns {any}
       */
      get(key) {
        return DRAG_CONTEXT.get(key)
      },
      /**
       * 获取注册的context
       * @param key
       * @returns {any}
       */
      getRegisterCtx(key) {
        return DRAG_CONTEXT.get(key)
      },
      /**
       *
       */
      clearAllCtx() {
        return DRAG_CONTEXT.clear()
      },
      getCtxs() {
        return DRAG_CONTEXT
      },
      emitter,
      /**
       * 创建rect观察窗
       * @param target
       */
      createRectInspect(target) {
        let clone = createInspect(target, 'rect',  {
          onMouseleave(e) {
            test1Tool()
          }
        })
        test1Tool(clone)
      },
      /**
       * 构建线观察窗
       * @param target
       */
      createLineInspect(target) {
        let clone = createInspect(target, 'line', {
        })
        testTools[0](clone)
      },
      clearAllTestToolsInspect() {
        clearTestToolsInspect()
      },
      clearLineInspect() {
        testTools[0]()
      },
      clearTest1LineInspect() {
        test1Tool()
      },
      /**
       * 刷新treee 菜单
       */
      reloadTreeMenu() {
        reloadTree()
      },
      onMouseEnter(e) {
        // console.log('onMouseEnter', e)
        let clone = createInspect(e.target, 'rect',  {
          onMouseleave() {
            test1Tool()
          }
        })
        test1Tool(clone)
      },
      /**
       * 实现mouse enter处理
       * @param target
       * @param targetVueCtx
       */
      onMouseEnter2(target, targetVueCtx) {
        let clone = createInspect(target, 'rect',  {
          onMouseleave(e) {
            test1Tool()
          },
          inspectContext: targetVueCtx
        })
        test1Tool(clone)
      },
      onCusConfigChange(uuid, config) {
        let _config = DRAG_INSTANSE.getConfig(uuid)
        if (!_config) {
          _config = {
            ins: {},
            common: {},
          }
        }
        _config.ins = config
        DRAG_INSTANSE.setConfig(uuid, _config)
        // console.log('onCusConfigChange', dragConfig)
      },
      // getCurrent() {
      //   return treeState.current ?? {}
      // },
      /**
       * 获取当前选中的组件
       * @returns {*}
       */
      getCurrentSelected() {
        return treeState.current ?? {}
      },
      highLight() {
        // console.log(context)
        setTimeout(() => {
          let dom = document.querySelectorAll('.z-drag-highlight')
          if (dom) {
            let arr = Array.of(...dom)
            // let clone = createInspect(arr[arr.length - 1], 'rect',  {
            //   onMouseleave(e) {
            //   }
            // })
            // clone.style.position = 'absolute'
            // test2Tool(clone)
            createHighlightRect(arr[arr.length - 1])
            // console.log(dom)
          }
        }, 30)
      },
      onGridDragEnter(cachedGridItem ) {
        state.cachedGridItem = cachedGridItem
      },
      onGridDragleave() {
        state.cachedGridItem = null
        // console.log('sdsdsds')
      },
      reloadTree() {
        reloadTree()
      },
      /**
       * 设置当前drag enter context
       * @param e
       */
      setCurrentDragEnterContext(e) {
        // console.log('onZLayoutInitDragEnter', e)
        currentDragEnterContext  = e
      },
      clearCurrentDragEnterContext() {
        currentDragEnterContext = null
      },
      /**
       * 创建树结构
       * @param label
       * @param id
       * @param label_xml
       * @param com
       * @returns {{tree_id, label_xml, label, id}}
       */
      buildTreeMenuItermStruct(label, id, label_xml, com) {
        return {
          label_xml,
          label,
          tree_id: id,
          itemUUID: id,
          id,
          com
        }
      },
      currentCtxUUID: '',
      setCurrentCtxUUID(uuid = '') {
        DRAG_INSTANSE.currentCtxUUID = uuid
        emitter.emit(DRAG_EVENTS.HIGHLIGHT, uuid)
      }
    }
    DRAG_INSTANSE.getInsVars = getInsVars
    DRAG_INSTANSE.getInsVarsV2 = getInsVarsV2
    provide('dragxml', DRAG_INSTANSE)
    provide('ZDragxmlInstance', DRAG_INSTANSE)
    globalThis.__DRAG_INSTANSE__ = DRAG_INSTANSE

    /**
     * 侧边栏树的状态
     * @type {UnwrapNestedRefs<{current: {}, showCurrent: boolean, data: *[], defaultProps: {children: string, label: string}, dragConfig: Map<any, any>, tplComponents: *[]}>}
     */
    let treeState = reactive({
      data: [],
      defaultProps: {
        children: 'children',
        label: 'label',
      },
      current: {},
      showCurrent: false,
      dragConfig,
      tplComponents: []
    })

    /**
     * 构建树的子集
     * @param child
     * @returns {*[]}
     */
    function buildTreeChild(child = []) {
      return child.map(item => {
        item.label = item.com.name
        item.tree_id = item.itemUUID
        item.id = item.itemUUID
        // console.log(item)
        if (item.com.DRAG_LABEL_XML) {
          item.label_xml = item.com.DRAG_LABEL_XML()
        }
        return item
      })
    }

    /**
     * 构建树
     * @param state
     * @returns {null[]|*[]}
     */
    function buildTree(state) {
      let layouts = state.layouts
      let layoutRefMap = state.layoutRefMap

      if (Array.isArray(layouts)) {
        // console.log(layouts)
        let result = layouts.map(layout => {
          // console.log(layout, layoutRefMap)
          // let ret = {
          //   label: 'item',
          //   children: []
          // }
          let ret = null
          let context = layoutRefMap[layout.uuid]?.el
          if (context) {
            // console.log(context)
            let columns = context.getChildren()
            // console.log(columns)

            if (columns.length  > 0) {
              let child = columns.map(function (column) {
                let child = column.children
                let res = []
                if (Array.isArray(child) && child.length > 0) {
                  let first = child[0]
                  // console.log(first.com)

                  if (first && first.com) {
                    let trueComDef = getTrueComDef(first.com)
                    // 对象
                    if (first.com.DRAG_SUB_FORM) {
                      let arr = buildTreeChild(child.slice(1))
                      res =  {
                        ...first,
                        label: first.com.name,
                        children: arr
                      }
                    }
                    // 数组包裹
                    else if(first.com.DRAG_ARRAY) {
                      // console.log('数组', child)
                      // res = buildTreeChild(child)
                      let arr = buildTreeChild(child.slice(1))
                      let children = [
                        {
                          ...arr[0],
                          children: arr.slice(1)
                        }
                      ]
                      res =  {
                        ...first,
                        label: first.com.name,
                        children: children
                      }
                    }
                    // 推拽Grid
                    else if(first.com.DRAG_GRID) {
                      // // console.log(first, child)
                      // res = buildTreeChild(child)
                      // // let layMap = layoutRefMap[first.con_uuid]
                      // // let gridLayout = layMap.el.getFirstCom()
                      // let itemUUID = first.itemUUID
                      // let context = DRAG_INSTANSE.getRegisterCtx(itemUUID)
                      // if (context) {
                      //   // console.log(context)
                      //   res[0].children = context.getTree()
                      // }
                    }

                    else {

                      if (trueComDef && trueComDef.ZDragCusExport) {
                        let itemUUID = first.itemUUID
                        let context = DRAG_INSTANSE.getRegisterCtx(itemUUID)
                        if (context && context.DRAG_BUILD_TREE) {
                          res = context.DRAG_BUILD_TREE()
                        }
                      } else {
                        res = buildTreeChild(child)
                      }
                    }

                    if (trueComDef.DRAG_LABEL_XML) {
                      res.label_xml = trueComDef.DRAG_LABEL_XML()
                    }
                  }
                  else {
                    res = buildTreeChild(child)
                  }
                }
                column.children = res
                // console.log('res', res)
                return column
              })
              ret = {
                label: 'row',
                children: child
              }
              if (child.length === 1) {
                // 单个组件
                if (Array.isArray(child[0].children)) {
                  ret = child[0].children[0]
                } else {
                  ret = child[0].children
                }
                if (ret) {
                  ret.tree_id = ret.itemUUID
                  ret.id = ret.itemUUID
                }
                // console.log(ret)
              } else {
                // console.log(child)
              }
            }

          }
          return ret
        }).filter( v => v)
        // console.log(result)
        return result
      }  else {
        return []
      }
    }

    /**
     * 刷新树
     */
    function reloadTree() {
      treeState.data = buildTree(state)
    }
    //

    let domRef = null
    function getRef(v) {
      domRef = v
    }

    function fromPoint(x, y) {
      return document.elementFromPoint(x, y)
    }


    /**
     *
     * @param id {string=}
     * @returns {(function(): void)|*}
     */
    function clearTool(id = TEST1_ID) {
      return function (clone) {
        let tool = document.getElementById(id)
        if (tool) {
          tool.innerHTML = ''
          if (clone) {
            tool.appendChild(clone)
          }
        }
      }
    }

    /**
     * 获取保存的配置
     * @param propKey
     * @param item
     * @returns {*}
     */
    function getParsedConfig(propKey, item) {
      let wrap_config = JSON5.parse(JSON5.stringify(
          DRAG_INSTANSE.getConfig(propKey) ?? {}))
      // console.log(wrap_config)
      if (wrap_config.ins && wrap_config.ins.rules) {
        wrap_config.ins.rules_json = wrap_config.ins.rules
        wrap_config.ins.rules = JSON5.parse( wrap_config.ins.rules)
        Reflect.deleteProperty(wrap_config.ins, 'rulesArr')
      }
      if (wrap_config.ins) {
        if (wrap_config.ins.computedFunIns) {
          Reflect.deleteProperty(wrap_config.ins, 'computedFunIns')
        }
      }
      // console.log(wrap_config, item)
      if (item && item.itemUUID) {
        let instanse2 = DRAG_INSTANSE.get(item.itemUUID)
        if (instanse2) {
          // console.log(instanse2)
          if (instanse2.DRAG_EXPORT) {
            let export_data = instanse2.DRAG_EXPORT() ?? {}
            let ins = wrap_config.ins ?? {}

            wrap_config.ins = deepMerge(export_data,
                ins)
          }
        }
      }
      return wrap_config
    }

    /**
     * 获取field key
     * @param config
     * @param prefix
     * @returns {string}
     */
    function getFieldKey(config, prefix = 'field_') {
      let field_key = prefix + ZY.rid(10)
      let server = config?.ins?.server ?? {}
      if (server && server.field_name) {
        field_key = server.field_name
      }
      if (server && server.server_field) {
        field_key = server.server_field
      }
      return field_key
    }

    /**
     * 处理服务器配置
     * @param config
     * @returns {{ins}|*}
     */
    function resolveServerConfig(config) {
      // console.log('resolveServerConfig', config)
      if (config.ins) {
        if (config.ins.ui) {
          Reflect.deleteProperty(config.ins, 'ui')
        }
        // if (config.ins.ui) {
        //   Reflect.deleteProperty(config.ins, 'ui')
        // }
      }
      return config
    }

    /**
     * 通过便利侧边栏tree获取数据结构
     * @param data
     * @param context
     * @param pathArr
     * @param options
     */
    function traveralTreeGetFormProps(data = [], context, pathArr = [], options = {}) {
      // console.log(pathArr)

      // const GRID_ITEM_WRAP_TAG = 'z-grid-item'

      let s_path = ZY.getObjPathFromPathArr(pathArr)
      let target = ZY.deepGet(context.res, s_path)


      let filterArr = data
      // if (options.DRAG_GRID) {
      //   arr = data.filter(item => {
      //     let gridUUID = item.GRID_UUID
      //     if (gridUUID === options.DRAG_GRID.gridUUID) {
      //       // return Array.isArray(item.children) && item.children.length > 0
      //       return true
      //     }
      //     return false
      //   })
      //   filterArr.filter(item => {
      //     return Array.isArray(item.children) && item.children.length > 0
      //   })
      // }

      lodash.each(data, function (item, index) {
        // console.log(item)
        let propKey = item.itemUUID
          if (!propKey) {
            return;
          }
          let com = item.com
          let isObjectItem = (Array.isArray(item.children) && item.children.length > 0)
          || (com && com.DRAG_SUB_FORM)


          let isDragGrid  = (com && com.DRAG_GRID);
          if (isDragGrid) {
            // console.log('DRAG_GRID', item)

            let config =  getParsedConfig(item.itemUUID)
            // console.log(config)

            context.pathArr = pathArr.concat( [] )
            options.DRAG_GRID = {
              wrap_start_tag: 'z-grid',
              wrap_end_tag: 'z-grid',
              gridUICONFIG: config?.ins?.ui ?? {},
              gridUUID: item.itemUUID,
            }
            traveralTreeGetFormProps(item.children, context, context.pathArr, options)
            return;
          }
          if (
              isObjectItem
          ) {
            let __type = 'object'
            let fieldKeyPrefix = 'sub__';
            if (com && com.DRAG_SUB_FORM) {
              fieldKeyPrefix = 'obj__'
            }

            if (com && com.DRAG_ARRAY) {
              fieldKeyPrefix = 'arr__'
              __type = 'array'
            }



            let config = getParsedConfig(propKey, item)
            let defType = ZY.lodash.get(config, 'ins.ui.defType')

            if (options.isServer) {
              config = resolveServerConfig(config)
            }
            let field_key = getFieldKey(config, fieldKeyPrefix)
            let properties = {}

            if (options.parentIsArray) {
              options.parentIsArray = false
              field_key = 'items'
            }

            // console.log(pathArr, properties)

            if (defType === 'arrayObj') {
              target[field_key] = {
                type: 'array',
                items: {
                  type: 'object',
                  properties
                },
                ...config.ins
              }
              // console.log(target)
              context.pathArr = pathArr.concat( [field_key, 'items', 'properties'] )
              options.parentIsArrayObject = true
              traveralTreeGetFormProps(item.children, context, context.pathArr, options)
            }
            else if (defType === 'grid') {
              // target[field_key] = {
              //   ...properties
              // }
              let _options = ZY.JSON5.parse(ZY.JSON5.stringify(options))
              context.pathArr = pathArr.concat( [] )
              options.parentIsGrid = true
              options.gridConfig = config
              options.gridOptions = _options
              traveralTreeGetFormProps(item.children, context, context.pathArr, options)
            }
            else if (defType === 'gridItem') {
              context.pathArr = pathArr.concat( [] )
              let _options = ZY.JSON5.parse(ZY.JSON5.stringify(options))
              options.parentIsGrid = true
              options.gridItemCtx = item
              options.gridItemIndex = index
              options.gridItemIsLast = index === data.length - 1
              options.gridItemConfig = config
              options.gridItemOptions = _options
              options.gridItemcontext = ZY.JSON5.parse(ZY.JSON5.stringify(context))
              // options.isInGridItem = true
              traveralTreeGetFormProps(item.children, context, context.pathArr, options)
            }
            else {
              if (__type === 'array' ) {
                target[field_key] = {
                  type: __type,
                  // items: {
                  //   type: 'object',
                  //   properties,
                  //   ...config.ins
                  // }
                  ...config.ins
                }
                context.pathArr = pathArr.concat( [field_key] )
                options.parentIsArray = true
                traveralTreeGetFormProps(item.children, context, context.pathArr, options)
              }
              else {
                target[field_key] = {
                  type: __type,
                  properties,
                  ...config.ins
                }
                // console.log(target)
                context.pathArr = pathArr.concat( [field_key, 'properties'] )
                traveralTreeGetFormProps(item.children, context, context.pathArr, options)
              }
            }

          } else {
            // 单个field
            // console.log(target)
            let config = getParsedConfig(propKey, item)
            if (options.isServer) {
              config = resolveServerConfig(config)
            }
            let field_key = getFieldKey(config)
            // console.log( options.parentIsGrid)
            if (target) {
              if (config?.ins?.ui?.defType === 'gridItem') {
                return;
              }
              if (config?.ins?.ui?.layout) {

                // console.log(
                //     config?.ins?.ui?.tag
                // )
                if (!config?.ins?.ui?.tag) {
                  return;
                }
                // return;
              }
              target[field_key] = {
                type: 'string',
                ...config.ins
              }

              if (!target[field_key].ui) {
                target[field_key].ui = {}
              }


              // console.log(options, config.ins, context.pathArr, target)

              if (options.gridItemCtx) {

                if (index === 0) {
                  target[field_key].ui.wrap_start_tags = [
                    ZRAGXML_VARS.grid_item_start_tag,
                  ]
                  if (options.gridItemIndex === 0) {
                    let _options = ZY.JSON5.parse(ZY.JSON5.stringify(options))
                    let gridConfig = _options?.gridItemOptions?.gridConfig
                    if (gridConfig) {
                      // console.log(gridConfig)
                      target[field_key].ui.wrap_start_config = gridConfig.ins
                    }
                    target[field_key].ui.wrap_start_tags.unshift(
                        ZRAGXML_VARS.wrap_start_tag,
                    )
                  }
                }
                if (index === data.length - 1) {
                  target[field_key].ui.wrap_end_tags = [
                    ZRAGXML_VARS.grid_item_end_tag,
                  ]
                  if (options.gridItemIsLast) {
                    target[field_key].ui.wrap_end_tags.push(
                        ZRAGXML_VARS.wrap_end_tag,
                    )
                  }
                }
                return
              }

              if (options.parentIsGrid) {
                let _options = ZY.JSON5.parse(ZY.JSON5.stringify(options))
                let curConfig = _options.gridConfig?.ins
                let tag = _options.gridConfig?.ins?.ui?.defTypeTag ?? ZRAGXML_VARS.wrap_start_tag
                // console.log(curConfig)
                if (index === 0) {
                  target[field_key].ui.wrap_start_tag = tag
                  if (curConfig) {
                    target[field_key].ui.wrap_start_config = curConfig
                  }
                }
                if (index === data.length - 1) {
                  target[field_key].ui.wrap_end_tag = tag
                }
              }

              // if (options.isInGridItem) {
              //   if (index === 0) {
              //     target[field_key].ui.wrap_start = `<${ZRAGXML_VARS.wrap_start_tag}>`
              //   }
              //   if (index === data.length - 1) {
              //     target[field_key].ui.wrap_end = `</${ZRAGXML_VARS.wrap_end_tag}>`
              //   }
              // }

              // if (!target[propKey].server) {
              //   target[propKey].server = {}
              // }
              // if (!target[propKey].server.field_name) {
              //   target[propKey].server.field_name = field_key
              // }
            }

          }

      })
    }

    /**
     * 获取配置
     * @param isServer
     * @returns {{ui: {styles: *[], widgetConfig: {}}, type: string, properties: {}}}
     */
    function getZProps(isServer =false) {
      let dragConfig = treeState.dragConfig
      // console.log(dragConfig)
      let context = {
        res: {},
        config: dragConfig,
        pathArr: [''],
        pathMap: {

        }
      }
      let propsDef = {
        type: 'object',
        ui: {
          styles: [

          ],
          widgetConfig: {

          }
        },
        properties: {

        }
      }
      if (Array.isArray(treeState.data)) {
        traveralTreeGetFormProps(treeState.data, context, [], {isServer})
        // console.log(context.res)
        // return context.res
        propsDef.properties = context.res
      }
      // return []
      return propsDef
    }


    let test1Tool = clearTool();
    let test2Tool = clearTool(TEST2_ID);
    let test3Tool = clearTool(TEST3_ID);

    let testTools = [
    ];

    TEST_IDS.forEach(v => {
      testTools.push(
          clearTool(v)
      )
    })

    /**
     * z layout init的当前context
     * @type {null|Object}
     */
    let currentDragEnterContext = null;


    /**
     *
     * @param ctx
     */
    function createHighlightRectV2(ctx) {
      function build() {
        // console.log('createHighlightRectV2', ctx)
        // ctx.isHighlight = true
        // ctx.zdrag__setCurHighLight(ctx.uuid)
        if (ctx && ctx.uuid) {
          DRAG_INSTANSE.setCurrentCtxUUID(ctx.uuid)
        }
      }
      build()
      _currentBuildV2 = build
    }


    /**
     *
     * @param dom
     */
    function createHighlightRect(dom) {
      function build() {
        // console.log(dom)
        let clone = createInspect(dom, 'rect',  {
          onMouseleave(e) {
          }
        })
        clone.style.position = 'fixed'
        test3Tool(clone)
      }
      build()
      _currentBuild = build
    }

    let _resizeCurrentBuildInterval = null
    window.addEventListener('resize', function () {
      clearTimeout(_resizeCurrentBuildInterval)
      // test3Tool()
      _resizeCurrentBuildInterval = setTimeout(function () {
        // console.log('_resizeCurrentBuildInterval', _currentBuild)
        nextTick(() => {
          if (_currentBuild) {
            _currentBuild()
          }
        })
      }, 30)
    })

    let _reloadCurrentBuildInterval = null
    window.addEventListener('zdragxml__toogleMenu', function () {
      // console.log('sdsds')
      clearTimeout(_reloadCurrentBuildInterval)
      test3Tool()
      _reloadCurrentBuildInterval = setTimeout(() => {
        nextTick(() => {
          if (_currentBuild) {
            _currentBuild()
          }
        })
      }, 1000)
    })




    function onMutation(mutations) {
      let el = document.querySelector('.z-drag-highlight')
      // console.log('mutations', el,  mutations[0]?.target?.classList.contains('playground') )
      if (Array.isArray(mutations) && mutations.length === 1 && mutations[0]?.target?.classList.contains('playground') ) {

        nextTick(() => {
          if (_currentBuild) {
            _currentBuild()
          }
        })
        return
      }
      if (!el) {
        test3Tool()
      }
    }

    let tplManager = initTplComponents(treeState);


    function list1ItemCls(element) {
      let filted = !element.name.includes(state.filterList)
      return {
        ['list-group-item--hidden']: filted
      }
    }

    function onDropStart(e) {
      state.isDragging = true
      state.disableDrag = true
      state.currentDragItem = e.item
    }

    function initLayoutRefs(item) {
      // console.log(uuid, state.layoutRefMap)
      let context = state.layoutRefMap[item.uuid]
      if (context && context.el) {
        let com = CustomVueComponent.resolve(item.dataset.name)
        context.el.initGrid(com)
      }
    }

    /**
     * 创建layout item
     */
    function createLayoutItem(dataset) {
      let com = CustomVueComponent.resolve(dataset.name)
      let uuid = ZY.rid()
      let columnMax = parseFloat(dataset.columnMax)
      if (!Number.isNaN(columnMax)) {
        dataset.columnMax = columnMax
      }
      // console.log('createLayoutItem', columnMax,item)
      return {
        uuid,
        columnMax,
        comName: dataset.name,
        dataset,
        com,
      }
    }

    // function appendLayout(dataset, {style = '', className = {}} = {}) {
    //   let item = createLayoutItem(dataset)
    //   item.style = style
    //   item.class = className
    //   state.layouts.push(item)
    // }

    /**
     *
     * @returns {*[]|*[]}
     */
    function buildUUIDS() {
      let el = getPlaygroundDOM()
      if (el) {
        let zs = Array.of(...el.querySelectorAll('[z-uuid-init-str]'))
        // console.log(zs, el)
        if (zs.length > 0) {
          // let df = zs.slice(1)
          let df = zs
          let uuids = df.filter(() => {
            return true
          }).map(dom => {
            return dom.getAttribute(Z_UUID_KEY)
          })
          // console.log(uuids)
          state.uuids = uuids
          return uuids
        }
        return []
      }
      return []
    }

    function reloadLayoutsSort() {
      let uuids = buildUUIDS()
      // console.log(uuids, state.layouts)

      let dlayouts = JSON5.parse(JSON5.stringify( state.layouts))

      let layouts = []
      uuids.forEach(uuid => {
        let index = dlayouts.findIndex(layout => {
          return layout.uuid === uuid
        })
        if (index > -1) {
          layouts.push(dlayouts[index])
        }
        // console.log(uuid, index)
      })
      state.layouts = layouts
      // console.log(uuids, state.layouts)
    }

    let sortable;
    let dragGroup = "drag-level" + ZY.rid(6);
    /**
     *
     */
    function rebuildSortable() {
      // let el = getPlaygroundDOM()
      // sortable = new Sortable(el, {
      //   group: dragGroup,
      //   onEnd: function (/**Event*/evt) {
      //     console.log('rebuildSortable', evt)
      //     test1Tool()
      //     test2Tool()
      //     reloadLayoutsSort()
      //
      //     nextTick(() => {
      //       reloadTree()
      //     })
      //   }
      // })
    }


    let _initScrollRef;
    function initScrollRef(el) {
      _initScrollRef = el
      // console.log(el)
    }

    function getInsVars() {
      // console.log(DRAG_INSTANSE.dragConfig)
      let ret = []
      DRAG_INSTANSE.getAllConfig().forEach((config, uuid) => {
        let fieldPaths = []
        let instance = DRAG_INSTANSE.getRegisterCtx(uuid)
        // console.log(instance.$el)
        if (instance) {
          let el = instance.$el
          if (el.hasAttribute('data-context-uuid')) {
            let contextUUID = el.getAttribute('data-context-uuid')
            let contextConfig = DRAG_INSTANSE.getConfig(contextUUID)
            // console.log(el, contextConfig)
            if (contextConfig && contextConfig?.ins?.server?.server_field) {
              fieldPaths.push(contextConfig?.ins?.server?.server_field)
            }
          }
          // console.log(el)
        }
        if (config && config?.ins?.ui?.label) {
          let field_name = config.ins?.server?.field_name
          // console.log(config.ins.computedFun)
          let computedFun = config?.ins?.computedFun
          if (field_name && !computedFun) {
            fieldPaths.push(field_name)
            let fieldPathsStr = ZY.JSON5.stringify(fieldPaths)
            // console.log(fieldPaths, fieldPathsStr)
            // let s_path = ZY.getObjPathFromPathArr(fieldPaths)
            ret.push(
                [
                  config.ins.ui.label,
                  'xy-text',
                  `val="M(${fieldPathsStr})" type-field=""`,
                  {
                    doc: ZY_EXT.marked(`1. field: ${fieldPathsStr}`)
                  }
                ]
            )
          }
        }
      })
      // console.log('getInsVars', ret)
      return ret
    }

    function getInsVarsV2() {
      // console.log(DRAG_INSTANSE.dragConfig)
      let ret = []
      DRAG_INSTANSE.getAllConfig().forEach((config, uuid) => {
        let fieldPaths = []
        let instance = DRAG_INSTANSE.getRegisterCtx(uuid)
        // console.log(instance.$el)
        if (instance) {
          let el = instance.$el
          if (el.hasAttribute('data-context-uuid')) {
            let contextUUID = el.getAttribute('data-context-uuid')
            let contextConfig = DRAG_INSTANSE.getConfig(contextUUID)
            // console.log(el, contextConfig)
            if (contextConfig && contextConfig?.ins?.server?.server_field) {
              fieldPaths.push(contextConfig?.ins?.server?.server_field)
            }
          }
          // console.log(el)
        }
        if (config && config?.ins?.ui?.label) {
          let field_name = config.ins?.server?.field_name
          // console.log(config.ins.computedFun)
          let computedFun = config?.ins?.computedFun
          if (field_name && !computedFun) {
            fieldPaths.push(field_name)
            let fieldPathsStr = ZY.JSON5.stringify(fieldPaths)
            // console.log(fieldPaths, fieldPathsStr)
            // let s_path = ZY.getObjPathFromPathArr(fieldPaths)
            ret.push(
                [
                  config.ins.ui.label,
                  'xy-text',
                  `val="${fieldPathsStr}" type-var-name=""`,
                  {
                    doc: ZY_EXT.marked(`1. field: ${fieldPathsStr}`)
                  }
                ]
            )
          }
        }
      })
      // console.log('getInsVars', ret)
      return ret
    }

    /**
     * 选择当前元素展示侧边栏
     * @param e
     * @param replace
     */
    function selectCurrentSetAsidePanel(e, replace = {}) {
      // console.log(e)
      treeState.current = {
        origin: e,
        uuid: e.itemUUID,
        ext: {},
        ...replace
      }
      treeState.showCurrent = false
      setTimeout(() => {
        treeState.showCurrent = true
      }, 300)
    }

    function getPlaygroundDOM() {
      return  document.getElementById(PLAY_ID)
    }

    function onDropEndItemsChanged(item) {
      test2Tool()
      initLayoutRefs(item)
      testTools.forEach(t => {
        t()
      });
      nextTick(() => {
        setTimeout(() => {
          buildUUIDS()
          rebuildSortable()
          reloadTree()
          // console.log('onDropEndItemsChanged', state.uuids)
        }, 50)
      })
    }

    function buildGridItem(dataset) {
      let {itemKey,context} = state.cachedGridItem
      // let target = e.target
      // let el = context.$el
      // console.log('onGridDragEnter', e, state.currentDragItem)
      // let dataset = state.currentDragItem?.dataset ?? {}
      // console.log(dataset)
      if (dataset.name) {
        let com = CustomVueComponent.resolve(dataset.name)
        if (!com.DRAG_GRID) {
          // console.log(dataset.name)
          context.initDomCom(itemKey, com)
          nextTick(() => {
            reloadTree()
          })
        }
      }
    }

    function appendLayout(uuid, item) {
      let index = state.uuids.findIndex((v) => v === uuid)
      // console.log(index, uuid)
      // let newUUID = ZY.rid()
      console.log(uuid, index)
      if (index > -1) {
        let newIndex = index + 1
        // let newIndex = index
        let newLen =  state.layouts.length
        state.layouts.splice(newIndex, 0, item)
        // console.log(newIndex, newLen)
        nextTick(() => {
          onDropEndItemsChanged(item)
          if (newIndex > newLen -1) {
            setTimeout(() => {
              _initScrollRef.setScrollTop(_initScrollRef.wrap.scrollHeight)
              // console.log(_initScrollRef.wrap.scrollHeight)
              // _initScrollRef.update()
              //   _initScrollRef.wrap.scrollTop = _initScrollRef.wrap.scrollHeight
            }, 300)
          }

        })
      }
    }

    /**
     * 当dargdrop end事件
     * @param e
     */
    function onDropEnd(e) {
      let playground = getPlaygroundDOM()
      state.isDragging = false
      setTimeout(() => {
        originalEvent = e.originalEvent
        // console.log('onDropEnd', originalEvent)

        let dataset = e?.item?.dataset ?? {}

        // if (state.cachedGridItem) {
        //   buildGridItem(dataset)
        //   return;
        // }


        currentToTarget = fromPoint(originalEvent.clientX, originalEvent.clientY)

        // console.log(currentToTarget, [originalEvent.clientX, originalEvent.clientY])
        if (!currentToTarget) {
          return;
        }

        /**
         * 获取组件定义
         * @type {*}
         */
        let com = CustomVueComponent.resolve(dataset.name)
        let item = createLayoutItem(dataset)


        if (currentToTarget.hasAttribute('z-drag-start')) {
          console.log('z-drag-start', item)
          state.layouts.unshift(item);
          nextTick(() => {
            onDropEndItemsChanged(item)
            test1Tool()
          })
          return;
        }
        if (playground.isEqualNode(currentToTarget)) {
          console.log('isEqualNode')
          state.layouts.push(item)
          nextTick(() => {
            onDropEndItemsChanged(item)
          })
          return;
        }

        if (currentToTarget.hasAttribute(Z_UUID_KEY)) {
          let uuid = currentToTarget.getAttribute(Z_UUID_KEY)
          // let index = Array.of(...playground.children).findIndex(v => {
          //   return v.getAttribute(Z_UUID_KEY) === uuid
          // })

          let index = state.uuids.findIndex((v) => v === uuid)
          // console.log(index, uuid, state.uuids)
          // let newUUID = ZY.rid()
          // console.log(uuid, index, newUUID)
          if (index > -1) {
            let newIndex = index + 1
            // let newIndex = index
            state.layouts.splice(newIndex, 0, item)
            nextTick(() => {
              onDropEndItemsChanged(item)
            })
          }
          return;
        }

        let trueDom = null
        if (playground.contains(currentToTarget)) {
          trueDom = getNestRenderDom(currentToTarget)
        }

        console.log(trueDom)

        if (trueDom && trueDom.parentElement && trueDom.parentElement.hasAttribute('z-drag-layout__column')) {
          let columnMax = parseInt(trueDom.parentElement.getAttribute('z-drag-layout__column'))

          if (columnMax < 2) {
            // console.log('sdsdsds', trueDom.parentElement.parentElement)
            let uuid = trueDom.parentElement.parentElement.getAttribute(Z_UUID_KEY)
            appendLayout(uuid, item)
          }
        }

        if (currentDragEnterContext && currentDragEnterContext.append) {
          // console.log(currentDragEnterContext, com, trueDom)
          currentDragEnterContext.append(com, trueDom)
        }

        if (currentDragEnterContext && currentDragEnterContext.onZDragXmlDropEnd) {
          currentDragEnterContext.onZDragXmlDropEnd(com, trueDom)
        }
      }, 30)
    }



    function getNestRenderDom(dom) {
      if (dom.classList.contains('render-dom-item')) {
        return dom
      }
      if (dom.parentElement) {
        return getNestRenderDom(dom.parentElement)
      }
      return null
    }

    function getLayoutRenderDom(dom) {
      if (dom.hasAttribute('layout-dom')) {
        return dom
      }
      // if (dom.parentElement) {
      //   return getNestRenderDom(dom.parentElement)
      // }
      return null
    }

    let currentInspectContext = null

    /**
     * 从 DOM 获取 vue context
     * @param trueDom
     * @returns {{con_uuid}|*|string}
     */
    function getDomComponentContext(trueDom) {
      if (trueDom.hasAttribute('z-uuid')) {
        let con_uuid = trueDom.getAttribute('z-uuid')
        let context = state.layoutRefMap[con_uuid]
        // removeLayout(con_uuid)
        // console.log(state.layoutRefMap, context)
        if (context && context.el) {
          let children = context.el.getChildren()
          if (children[0] && children[0].children[0]) {
            return children[0].children[0]
          }
        }
      }
      else if (trueDom.hasAttribute('z-drag-grid-item')) {
        // let dataset = trueDom.dataset
        // let gridUUId = dataset.gridId
        // let gridIns = DRAG_INSTANSE.get(gridUUId)
        // if (gridIns) {
        //   let dom = gridIns.getDom(dataset.key)
        //   if (dom) {
        //     return dom.def
        //   }
        // }
      }
      /**
       * 获取grid item内部组件instance
       */
      else if (trueDom.hasAttribute('z-drag-grid-com')) {
        let dataset = trueDom.dataset
        let gridUUId = dataset.gridUuid
        let itemUUId= trueDom.getAttribute('data-item-uuid')
        let gridIns = DRAG_INSTANSE.get(gridUUId)
        if (gridIns) {
          let ctx = gridIns.getInsMap(itemUUId)
          // console.log(ctx)
          return {
            com: ctx.$options,
            ctx: ctx
          }
        }
        // console.log(dataset, gridIns)
      }
      else {
        let trueDom_uuid = app.findUUIDfromClassList(trueDom)
        let layout_uuid = app.findUUIDfromClassList(trueDom, DATA_LAYOUT_UUID_KEY)
        let layout_item_uuid = app.findUUIDfromClassList(trueDom, DATA_LAYOUT_ITEM_UUID_KEY)
        // console.log(layout_uuid, trueDom_uuid)
        let context = state.layoutRefs[layout_uuid]
        if (context) {
          currentInspectContext = context.findCom(trueDom_uuid, layout_item_uuid)
          if (currentInspectContext.con_uuid) {
            return currentInspectContext
          }
        }
      }
    }

    function resolveZDragLoopContextFromDOM(trueDom, inspectContext) {
      if (trueDom.hasAttribute('z-drag-loop-uuid')) {
        let uuid = trueDom.getAttribute('z-drag-loop-uuid')
        if (!inspectContext) {
          let ctx = DRAG_INSTANSE.getRegisterCtx(uuid)
          inspectContext = {
            com: ctx.$options,
            ctx
          }
        }
      }
    }

    /**
     * 创建观察
     * @param trueDom
     * @param type
     * @param options
     * @returns {HTMLElement | HTMLDivElement | any}
     */
    function createInspect(trueDom, type, options = { inspectContext : {}}) {

      // console.log(options)
      let inspectContext = {}
      if (options.inspectContext) {
        inspectContext = options.inspectContext
        // context = options.inspectContext
      } else {
        inspectContext = getDomComponentContext(trueDom)
      }
      resolveZDragLoopContextFromDOM(trueDom, inspectContext)

      function handleButtonClick() {
        // console.log(inspectContext, trueDom)
        if (inspectContext && !inspectContext.ctx && inspectContext.itemUUID ) {
          inspectContext.ctx = DRAG_INSTANSE.getRegisterCtx(inspectContext.itemUUID)
        }
        if (inspectContext && inspectContext.ctx) {
          // console.log('inspectContext',)
          if ( inspectContext.ctx.handleDragXmlButtonClick) {
            inspectContext.ctx.handleDragXmlButtonClick({
              selectCurrentSetAsidePanel
            })
            setTimeout(() => {
              // createHighlightRect(trueDom)
              createHighlightRectV2(inspectContext.ctx)
            }, 30)
            return;
          }
        }
        if (trueDom.hasAttribute('z-uuid')) {
          let con_uuid = trueDom.getAttribute('z-uuid')
          let context = state.layoutRefMap[con_uuid]
          // removeLayout(con_uuid)
          // console.log(state.layoutRefMap, context)
          if (context && context.el) {
            let children = context.el.getChildren()
            if (children[0] && children[0].children[0]) {
              let currentInspectContext = children[0].children[0]
              selectCurrentSetAsidePanel(currentInspectContext)
              // console.log(context, currentInspectContext)
            }
          }
        }
        else if (trueDom.hasAttribute('z-drag-grid-item')) {
          let dataset = trueDom.dataset
          let gridUUId = dataset.gridId
          let gridIns = DRAG_INSTANSE.getRegisterCtx(gridUUId)
          if (gridIns) {
            let dom = gridIns.getDom(dataset.key)
            if (dom) {
              selectCurrentSetAsidePanel(dom.def)
            }
          }
        }
        else if (trueDom.hasAttribute('z-drag-grid-com')) {
          // console.log(context)
          selectCurrentSetAsidePanel(context, {
            uuid: inspectContext.ctx.uuid
          })
        }
        else {
          let trueDom_uuid = app.findUUIDfromClassList(trueDom)
          let layout_uuid = app.findUUIDfromClassList(trueDom, DATA_LAYOUT_UUID_KEY)
          let layout_item_uuid = app.findUUIDfromClassList(trueDom, DATA_LAYOUT_ITEM_UUID_KEY)
          // console.log(layout_uuid, trueDom_uuid)
          let context = state.layoutRefs[layout_uuid]
          if (context) {
            currentInspectContext = context.findCom(trueDom_uuid, layout_item_uuid)
            if (currentInspectContext.con_uuid) {
              selectCurrentSetAsidePanel(currentInspectContext)
            }
          }
        }
      }

      function handleDelClick() {
        // console.log(trueDom)
        if (inspectContext && inspectContext.ctx) {
          // console.log('inspectContext',)

          if ( inspectContext.ctx.handleDragXmlButtonDelete) {
            inspectContext.ctx.handleDragXmlButtonDelete({
              trueDom,
              ctx: inspectContext.ctx,
              clearConfigByID,
              reloadTree,
              DRAG_INSTANSE
            })


          }
        }

        // z-uuid 是 z-dragxml 第一层
        if (trueDom.hasAttribute(Z_INIT_UUID_KEY)) {
          let con_uuid = trueDom.getAttribute(Z_INIT_UUID_KEY)

          let context = state.layoutRefMap[con_uuid]
          if (context && context.el) {
            // console.dir(context)
            let children = context.el.getChildColumn()
            // console.log(children, dragConfig)
            ZY.lodash.each(children, function (item) {
              clearConfigByID(item.itemUUID)
            })

            removeLayout(con_uuid)
          }
        }
        else if (trueDom.hasAttribute('z-drag-grid-item')) {

        }
        else if (trueDom.hasAttribute('z-drag-grid-com')) {
           // console.log(context)
           let ctx = context.ctx;
           if (ctx && ctx.ZDragGridIns) {
             ctx.ZDragGridIns.remove(ctx)
             clearConfigByID(ctx.uuid)
           }
        }
        else {
          let trueDom_uuid = app.findUUIDfromClassList(trueDom)
          let layout_uuid = app.findUUIDfromClassList(trueDom, DATA_LAYOUT_UUID_KEY)
          let layout_item_uuid = app.findUUIDfromClassList(trueDom, DATA_LAYOUT_ITEM_UUID_KEY)
          // console.log(trueDom_uuid)
          // 尝试获取改组件是否注册过ctx
          let trueDomContext = DRAG_INSTANSE.getRegisterCtx(trueDom_uuid)
          if (trueDomContext) {
            clearConfigByID(trueDomContext.itemUUID)
          }
          // console.log(trueDomContext)
          // console.log(layout_uuid, trueDom_uuid)
          let layoutInitContext = state.layoutRefs[layout_uuid]
          if (layoutInitContext) {
            let children = layoutInitContext.getChildColumn()
            console.log(children)

            // 兼容旧版本查找选中的元素
            currentInspectContext = layoutInitContext.findCom(trueDom_uuid, layout_item_uuid)
            if (currentInspectContext) {
              clearConfigByID(currentInspectContext.itemUUID)
            }

            if (children.length < 3) {
              removeLayout(currentInspectContext.con_uuid)
            }

            layoutInitContext.removeChildByUUID(trueDom_uuid)
            reloadTree()
          }
        }

        clearTreeStateCurrent()
      }

      // console.log(trueDom)

      // 单一组件不可以
      if (type === 'line') {
        if (trueDom && trueDom.parentElement && trueDom.parentElement
            && trueDom.parentElement.hasAttribute('z-drag-layout__column')
            ) {
          let columnMax = parseInt(trueDom.parentElement.getAttribute('z-drag-layout__column'))
          // console.log(columnMax)
          if (columnMax < 2) {
            trueDom = trueDom.parentElement.parentElement
          }
        }
      }

      let clone = document.createElement('div')
      let computedStyle = getComputedStyle(trueDom)
      // console.log(computedStyle.marginBottom)
      let marginBottom = parseFloat(computedStyle.marginBottom)
      let marginTop = parseFloat(computedStyle.marginTop)
      let client = trueDom.getBoundingClientRect()
      // console.log(clone, client)
      clone.setAttribute('data-type', type)
      // clone.style.position = 'fixed'
      clone.style.position = 'fixed'
      clone.style.left = client.left + 'px'
      // clone.style.top = (client.top - marginBottom) + 'px'
      clone.style.width = client.width + 'px'
      clone.style.zIndex = 111
      if (type === 'line') {
        let top = ( client.top + client.height )
        if (options.cusTop) {
          top = options.cusTop(top)
        }
        clone.style.top = top + 'px'
        clone.style.height = 1 + 'px'

      }
      else if (type === 'rect') {
        clone.style.top = (client.top - marginTop) + 'px'
        clone.style.height = (client.height + marginTop + marginBottom + 1) + 'px'
        // clone.style.height = (client.height + marginTop + 1) + 'px'

        clone.addEventListener('mouseleave', function (e) {
          if (options && options.onMouseleave) {
            options.onMouseleave(e)
          }
        })

        let button1 = document.createElement('button')
        button1.classList.add('zdragxml__control-button')
        button1.classList.add('zdragxml__edit-button')
        button1.type = 'button'
        button1.textContent = '编辑'
        button1.addEventListener('click', handleButtonClick)
        // clone.appendChild(button1)

        let button2 = document.createElement('button')
        button2.classList.add('zdragxml__control-button')
        button2.classList.add('zdragxml__del-button')
        button2.type = 'button'
        button2.textContent = '删除'
        button2.addEventListener('click', handleDelClick)
        // clone.appendChild(button2)

        // console.log(inspectContext)
        let labelXml =  ((inspectContext && inspectContext.label_xml) ?? (inspectContext && inspectContext.label)) ?? ''
        if (inspectContext && inspectContext.com) {
          let comDef = CustomVueComponent.resolve(inspectContext.com)
          if (inspectContext.com.name) {
            comDef = CustomVueComponent.resolve(inspectContext.com.name)
          }
          if (comDef && comDef.DRAG_LABEL_XML) {
            labelXml = comDef.DRAG_LABEL_XML()
          }
          // console.log(comDef, labelXml)
        } else {
        //  处理grid item的组件的捕获
        }
        // 如果有ctx
        if (inspectContext && inspectContext.ctx) {
          let comDef;
          if (inspectContext.ctx.$options) {
            comDef = inspectContext.ctx.$options
          }
          if (comDef && comDef.DRAG_LABEL_XML) {
            labelXml = comDef.DRAG_LABEL_XML()
          }
        }



        let label1 = document.createElement('div')
        label1.className = 'inspect-label'
        label1.innerHTML = labelXml
        if (inspectContext) {
          // console.log(labelXml, context.com, trueDom)
          clone.append(button1, button2, label1)
        }

      }
      clone.setAttribute('current-to-move', type)
      return clone
    }

    /**
     * 观察DOM
     * @param e
     * @param type
     * @param actionFun
     * @param findDom
     * @param options
     */
    function inspectDom(e, type = 'line', {
      actionFun = test1Tool, findDom = getNestRenderDom, options = {}
    } = {}) {
      let playground = getPlaygroundDOM()
      // console.log(playground, e.pageX, e.pageY)
      currentToMove = fromPoint(e.clientX, e.clientY)
      // console.log(currentToMove)
      let trueDom = null
      if (!currentToMove) {
        return
      }
      if (currentToMove && playground.contains(currentToMove)) {
        trueDom = findDom(currentToMove)
      }
      // console.log(trueDom)
      // if (trueDom && trueDom.hasAttribute('no-drag-line')) {
      //   return
      // }
      if (currentToMove.hasAttribute('z-drag-start')) {
        let clone = createInspect(currentToMove, type, options)
        actionFun(clone)
        return;
      }
      if (trueDom) {
        let clone = createInspect(trueDom, type, options)
        actionFun(clone)
      }  else {
        actionFun()
      }
    }

    function onMouseMove(e) {
      // inspectDom(e,'rect')
      // inspectDom(e,'rect', {
      //   actionFun: test2Tool,
      //   findDom: getLayoutRenderDom
      // })
      // clearTool()
      let testId1DOM = document.getElementById(TEST1_ID)
      let playground = getPlaygroundDOM()
      currentToMove = fromPoint(e.clientX, e.clientY)
      // console.log(currentToMove)
      // let trueDom = null
      if (currentToMove && playground.contains(currentToMove)) {
        // trueDom = findDom(currentToMove)
        // console.log(trueDom)
      }
       else {
         if (testId1DOM.contains(currentToMove)) {
           // console.log('sdsdsds')
         } else  {
           // console.log(currentToMove, testId1DOM.children)
           if (testId1DOM.children && testId1DOM.children.length > 0) {
             test1Tool()
           }
         }
      }
    }


    function onDragMove(e) {
      // console.log(e.target)
      let isInDragLoop = e.target.closest('.z-drag-loop')
      // console.log(isInDragLoop)
      if (e.target.hasAttribute('no-drag-line') || isInDragLoop) {
        test1Tool()
      } else {
        inspectDom(e, {
          options: {
            cusTop(top) {
              return top - 6
            }
          }
        })
      }
      inspectDom(e,'line', {
        actionFun: test2Tool,
        findDom: getLayoutRenderDom,
        options: {
          cusTop(top) {
            return top - 6
          }
        }
      })
    }

    /**
     * 当z-layout-init dragenter事件触发
     * @param e
     */
    function onZLayoutInitDragEnter(e) {
      // console.log('onZLayoutInitDragEnter', e)
      currentDragEnterContext  = e
      test1Tool()
      test2Tool()
      clearTestToolsInspect()
    }

    /**
     * 清除当前选中的panel
     */
    function clearTreeStateCurrent() {
      // 清除当前current选中
      if (treeState.current.uuid) {
        // console.log(treeState.current.uuid, dragConfig)
        if (!DRAG_INSTANSE.hasConfig(treeState.current.uuid)) {
          treeState.current = {}
        }
      }
    }

    /**
     *
     * @param data
     */
    function clearConfig(data) {
      if (data && data.itemUUID) {
        DRAG_INSTANSE.delConfig(data.itemUUID)
      }
    }


    /**
     * 删除缓存配置
     * @param id
     */
    function clearConfigByID(id) {
      if (id) {
        DRAG_INSTANSE.delConfig(id)
      }
    }

    /**
     * removeSubLayout
     * @param con_uuid {string}
     * @param data {{}}
     */
    function removeSubLayout(con_uuid, data = {}) {
      let layouMapItem = state.layoutRefMap[con_uuid]
      // console.log(layouMapItem)
      if (layouMapItem && layouMapItem.el && layouMapItem.el.removeChild) {
        layouMapItem.el.removeChild(data)
      }
      // Reflect.deleteProperty(state.layoutRefMap, con_uuid)
      reloadTree()
    }

    /**
     * removeLayout 删除一个ZLayoutInit
     * @param con_uuid {string}
     * @param data {{}}
     */
    function removeLayout(con_uuid, data = {}) {
      let index = state.layouts.findIndex(v => {
        return v.uuid === con_uuid
      })
      if (index > -1) {
        // let layout = state.layouts[index]
        let layouMapItem = state.layoutRefMap[con_uuid]
        let layoutUUID = layouMapItem.layoutUUID
        // let layoutRef = state.layoutRefs[layoutUUID]
        Reflect.deleteProperty(state.layoutRefs, layoutUUID)
        Reflect.deleteProperty(state.layoutRefMap, con_uuid)
        state.layouts.splice(index, 1)
        buildUUIDS()
        reloadTree()
        // console.log(layout, layouMapItem, layoutRef)
      }
    }

    /**
     * 设置layoutRefMap
     * @param item
     * @returns {(function(*): void)|*}
     */
    function initZlayoutInitRef(item) {
      // console.log('item', item)
      return function (el) {
        if (el) {
          state.layoutRefMap[item.uuid] = {
            el,
            layoutUUID: el.state.layoutUUID,
            item
          }
          state.layoutRefs[el.state.layoutUUID] = el
        }
      }
  }

    function onClearIndex() {
      // console.log('onClearIndex')
      test1Tool()
    }

    /**
     * 删除tree上的node
     * @param node
     * @param data
     */
    function removeTreeNode(node, data) {
      let {com = {}} = data

      // console.log(data)
      // 当选中的是grid 中的元素
      if (data.gridUUID && data.itemUUID && data['z-drag-grid-com']) {
        console.log('removeTreeNode', node, data, com)
        let gridIns = DRAG_INSTANSE.getRegisterCtx(data.gridUUID)
        if (gridIns) {
          // grid item中组件的ctx
          let ctx = gridIns.getInsMap(data.itemUUID)
          // console.log(ctx)
          if (ctx) {
            ctx.ZDragGridIns.remove(ctx)
            clearConfigByID(ctx.uuid)
            nextTick(() => {
              reloadTree()
            })
          }
        }
      }
      else if (data.root_id) {
        // console.log('sdsdsds')
        let rootCtx = DRAG_INSTANSE.getRegisterCtx(data.root_id)
        if (rootCtx) {
          if (rootCtx.handleDragXmlDelete) {
            rootCtx.handleDragXmlDelete(data, {
              clearConfigByID,
              reloadTree
            })
          }
        }
      }
      // 自定义export
      else if (data.com.ZDragCusExport) {
        let rootCtx = DRAG_INSTANSE.getRegisterCtx(data.itemUUID)
        if (!rootCtx) {
          return;
        }
        let isTop = rootCtx.checkIsTopZDragLoop()
        // console.log(rootCtx, isTop)
        // 如果是第一级就直接删除
        if (isTop) {
          let layout_uuid = data.layout_uuid
          let layout = state.layoutRefs[layout_uuid]

          rootCtx.deleteAllWidgets({
            clearConfigByID
          });
          // console.log(layout.uuid)
          clearConfigByID(data.itemUUID)
          removeLayout(layout.uuid)
        } else {
          let parent = rootCtx.getParetntZDragLoop()
          // console.log(parent,data)
          rootCtx.deleteAllWidgets({
            clearConfigByID
          });
          if (parent) {
            parent.deleteWidgetByUUID(data.itemUUID)
          }
          reloadTree()
        }
      }
      else {
        // console.log(com, node.parent)
        if (com.DRAG_SUB_FORM) {
          lodash.each(node.childNodes, (childNode) => {
            let childNodeData = childNode.data
            // console.log(childNode, childNodeData)
            clearConfig(childNodeData)
          })
          clearConfig(data)
          // console.log(dragConfig)
          removeLayout(data.con_uuid, data)
        }
        else {
          if (node.parent && node.parent.data?.com?.DRAG_SUB_FORM) {
            clearConfig(data)
            // console.log(dragConfig, data)
            removeSubLayout(data.con_uuid, data)
          }
          else if (node.parent && node.parent.data?.DRAG_GRID_ITEM) {
            let parentData =  node.parent.data
            // console.log(parentData)
            let parentRef = DRAG_INSTANSE.getRegisterCtx(parentData.GRID_UUID)
            // console.log(parentRef)
            if (parentRef) {
              parentRef.clearGridItem(data.gridItemUUID)
              // console.log(treeState.current, data)
              if (treeState.current.uuid === data.uuid) {
                treeState.current = {}
              }
              nextTick(() => {
                reloadTree()
              })
            }
            // console.log('dsdsdsds', parentData, data)
          }
          else {
            clearConfig(data)
            removeLayout(data.con_uuid, data)
          }
        }
      }

      clearTreeStateCurrent()
    }

    function onChangedLayout() {
      reloadTree()
    }

    /**
     * 当子表单内部拖动结束后
     */
    function onDragEnd() {
      reloadTree()
    }

    /**
     * 左侧侧边栏选中元素
     * @param e
     */
    function handleTreeNodeClick(e) {
      // console.log('handleTreeNodeClick', e)
      let {config = {}} = e
      treeState.current = {
        origin: e,
        uuid: e.itemUUID,
        ext: {},
      }
      treeState.showCurrent = false
      setTimeout(() => {
        treeState.showCurrent = true
      }, 300)
      if (config.com) {
        let def = CustomVueComponent.resolve(config.com)
        treeState.current.cusEditor =  def.CUS_EDITOR()
      }
      // console.log(treeState.current)

    }

    /**
     * 设置组件侧边栏配置
     * @returns {Promise<{default: {init: {args: {src: string}, def: {parts: [{def: {}, computed: {}, name: string, serviceTpl: {args: {src: string}, def: {}}, type: string}], constants: {}}}, defaultVal: {}, name: string}}>}
     */
    async function resolveConfig() {
      let current  = treeState.current
      let origin = current.origin
      let uuid = current.uuid
      // 组件源
      let com = origin.com
      // 组件定义
      let comDef = null
      if (com.name) {
        comDef = CustomVueComponent.resolve(com.name)
      }
      treeState.current.com_name = com.name
      treeState.current.com_xml = treeState.current?.origin?.label_xml ?? com.name
      // console.log(treeState?.current?.origin?.com)
      if (treeState?.current?.origin?.com?.DRAG_LABEL_XML) {
        treeState.current.com_xml = treeState?.current?.origin?.com?.DRAG_LABEL_XML()
      }
      if (treeState?.current?.origin?.com?.name) {
        let def = CustomVueComponent.resolve(treeState?.current?.origin?.com?.name)
        if (def.DRAG_LABEL_XML) {
          treeState.current.com_xml = def.DRAG_LABEL_XML();
        }
      }


      let widgetConfigProps = {
        disabled: QuickBooleanWithNull('禁用', {
          ui: {
            class: [
              'zdragxml__prop__base_widget'
            ]
          }
        }),
        readonly: QuickBooleanWithNull('只读', {
          ui: {
            class: [
              'zdragxml__prop__base_widget'
            ]
          }
        }),
        css_style: {
          type: 'string',
          computedProp: 'ui_css',
          ui: {
            styles: [
              ['height', 0],
              ['overflow', 'hidden'],
            ],
            widgetConfig: {
              type: 'textarea',
              readonly: true,
            }
          }
        }
      }

      /**
       * 每个widget （zdrag_xxx） 的DRAG_CONFIG的computed
       */
      let widgetComputedProps = {}

      // console.log(current, com)
      // 错误代码
      if (com.DRAG_CONFIG) {
        let _config  = com.DRAG_CONFIG(current) ?? {}
        widgetConfigProps = Object.assign(widgetConfigProps, _config.props)
      }
      if (comDef && comDef.DRAG_CONFIG) {
        let _config  = comDef.DRAG_CONFIG(current) ?? {}
        widgetConfigProps = Object.assign(widgetConfigProps, _config.props)
      }
      // end 错误代码

      let instanse = DRAG_INSTANSE.getRegisterCtx(uuid)
      let _uiConfigProps = {}
      // console.log(instanse, instanse.DRAG_UI_CONFIG)
      if (instanse.DRAG_UI_CONFIG) {
        _uiConfigProps  = instanse.DRAG_UI_CONFIG() ?? {}
      }

      if (instanse.$options && instanse.$options.DRAG_UI_CONFIG) {
        _uiConfigProps  = instanse.$options.DRAG_UI_CONFIG() ?? {}
      }

      if (instanse && instanse.DRAG_CONFIG) {
        widgetConfigProps = Object.assign(widgetConfigProps, instanse.DRAG_CONFIG(current)?.props )

        widgetComputedProps = instanse.DRAG_CONFIG(current)?.computed
      }
      // console.log(com,widgetConfigProps)
      let base_type_props = {
        type: {
          type: 'string',
          wrap_start: '<xy-tab-content label="常见">',
          ui: {
            label: '类型',
            // widget: 'CusSelect',
            widget: 'CusSuggest',
            widgetConfig: {
              // inputStyle: 'width: 350px',
              enums: "ROOT_STATE('tools.propTypes2', [])",
              mode: 'select',
              readonly: true,
            },
            class: [
              'zdragxml__prop__base'
            ]
          },
        },
        sub_type: {
          type: 'string',
          ui: {
            label: '子类型',
            // widget: 'CusSelect',
            widget: 'CusSuggest',
            widgetConfig: {
              // inputStyle: 'width: 350px',
              enums: "ROOT_GETTERS('subTypes', [MODEL('type', '')])",
              mode: 'select',
              // readonly: true,
            },
            class: [
              'zdragxml__prop__base'
            ]
          },
        },
        // defaultVal: {
        //   type: 'string',
        //   ui: {
        //     label: '默认值',
        //   }
        // },
      }

      let _baseConfigProps = {}
      // console.log(instanse)
      if (instanse && instanse.$options && instanse.$options.DRAG_BASE_CONFIG) {
        _baseConfigProps  = instanse.$options.DRAG_BASE_CONFIG() ?? {}
      }
      // console.log(_baseConfigProps)

      base_type_props = Object.assign(base_type_props, _baseConfigProps)

      let com_def = CustomVueComponent.resolve(com.name)
      // console.log(com_def)
      if (com_def.DRAG_DEFAULT_VAL) {
        base_type_props.defaultVal = com_def.DRAG_DEFAULT_VAL()
      }
      let base_ui_props =  {
        type: 'object',
        ui: {
          label: "UI",
          labelCls: 'panel__base_ui_props__header'
        },
        properties: {
          // ref: {
          //   type: 'string',
          //   ui: {
          //     label: '引用',
          //     class: [
          //       'zdragxml__prop__ref'
          //     ]
          //   }
          // },
          label: {
            type: 'string',
            ui: {
              label: '标题',
              class: [
                'zdragxml__prop__l1',
                'zdragxml__prop__label'
              ]
            }
          },
          desc: {
            type: 'string',
            ui: {
              label: '描述',
              widgetConfig: {
                type: 'textarea'
              },
              class: [
                'zdragxml__prop__l1',
                'zdragxml__prop__desc'
              ]
            }
          },
          // hiddenLabel: QuickBooleanWithNull('隐藏标题', {
          //   ui: {
          //     class: [
          //       'zdragxml__prop__l2',
          //       'zdragxml__prop__hiddenLabel'
          //     ]
          //   }
          // }),
          label_item_json: {
            type: 'string',
            ui: {
              class: [
                'zdragxml__prop__l1',
                'zdragxml__prop__label_item_json'
              ],
              label: ' ',
              widget: 'CusLabelItem',
              widgetConfig: {
                type: 'textarea'
              },
              form_item: {
                labelWidth: '0px',
                class: "form-item--no-label-padding"
              }
            }
          },
          column: {
            type: 'string',
            ui: {
              label: '宽度',
              class: [
                'zdragxml__prop__l1',
                'zdragxml__prop__column'
              ],
              widget: 'CusSuggest',
              widgetConfig: {
                suggest:new Array(24).fill().map((v, index) => {
                  // console.log(index)
                  let newIndex = index + 1
                  return  {
                    label: `${newIndex}/24`,
                    value: ZY2.helpers.toDecimal2((newIndex/24*100)) + '%'
                  }
                }),
                placement: 'top-start',
                listStyle: 'height: 270px; overflow: auto;'
              }
            }
          },
          ..._uiConfigProps,
          widgetConfig: {
            type: 'object',
            ui: {
              label: "UI 配置",
              labelCls: 'panel__base_ui_widgetconfig__header'
            },
            properties: widgetConfigProps
          },
        }
      }
      let base_server_props = {
        type: 'object',
        wrap_start: '<xy-tab-content label="高级">',
        wrap_end: '</xy-tab-content>',
        ui: {
          label: '服务器'
        },
        properties: {
          field_name: {
            type: 'string',
            ui: {
              label: '字符ID',
              widgetConfig: {
                readonly: true
              },
              form_item: {
                labelWidth: '120px'
              }
            }
          },
          server_field: {
            type: 'string',
            ui: {
              notice: '修改会导致部分服务需重新配置',
              label: '服务器字段',
              attrs: [
                ['need-control', 1  ]
              ],
              widgetConfig: {
              },
              form_item: {
                labelWidth: '120px'
              }
            }
          },
          events: {
            type: 'string',
            ui: {
              label: ' ',
              widget: 'CusComEvents2',
              widgetConfig: {},
              form_item: {
                labelWidth: '0px',
                class: "form-item--no-label-padding"
              }
            }
          },
          watches: {
            type: 'string',
            ui: {
              label: ' ',
              widget: 'CusComWatches',
              widgetConfig: {},
              form_item: {
                labelWidth: '0px',
                class: "form-item--no-label-padding"
              }
            }
          }
        }
      }
      let base_form_props = {
        base_other_prop: {
          wrap_end: '</xy-tab-content>',
          ui: {
            attrs: [
              ['style', 'height: 0; overflow: hidden']
            ],
          }
        }
      }
      // console.log(comDef)
      // 如果是field才有表单验证


      globalThis[imeVarsFunName] =  function () {
        return  getInsVars()
      }

      if (comDef?.DRAG_FIELD) {
        base_type_props = {
          ...base_type_props,
          computedFun: {
            type: 'string',
            computedProp: 'get_computedFunIns',
            ui: {
              attrs: [
                ['style', 'height: 0; overflow: hidden']
              ],
              widgetConfig: {
                type: 'textarea',
                readonly: true,
              }
            }
          },
          computedFunIns: {
            type: 'string',
            ui: {
              label: '计算属性',
              widget: 'CusInsert',
              widgetConfig: {
                insText: [
                ],
                insFun: [
                  // 'MODEL',
                  ...Object.keys(globalThis.COM_FORM_COMMON_EVAL_FUNS)
                ],
                insVars: getInsVars(),
                version: 1,
                imeVars: `globalThis['${imeVarsFunName}']()`
              },
              class: [
                'zdragxml__prop__l2',
                'zdragxml__prop__computedFunIns'
              ]
            }
          },
        }

        base_form_props = {
          rules: {
            type: 'string',
            // hidden: true,
            computedProp: 'srules',
            ui: {
              attrs: [
                ['style', 'height: 0; overflow: hidden']
              ],
              label: '验证规则',
              widgetConfig: {
                type: 'textarea',
                disabled: true
              }
            }
          },
          rulesArr: {
            type: 'array',
            ui: {
              label: '校验规则',
            },
            wrap_end: '</xy-tab-content>',
            items: {
              type: "object",
              properties: {
                value: {
                  type: 'string',
                  ui: {
                    form_item: {
                      labelWidth: '0px'
                    },
                    label: ' ',
                    widget: 'CusFormRules',
                    widgetConfig: {
                    }
                  },
                },
              }
            }
          },
        }
      }
      let properties = {
        ...base_type_props,
        ui: base_ui_props,
      }

      // console.log(com)
      // if (!com.DRAG_GRID) {
        properties = {
          ...base_type_props,
          ui: base_ui_props,
          ...base_form_props,
          server: base_server_props,
          css: {
            type: 'string',
            wrap_start: '<xy-tab-content label="样式">',
            wrap_end: '</xy-tab-content>',
            ui: {
              label: '',
              widget: 'CusStyleEditor',
              hiddenLabel: true,
              form_item: {
                labelWidth: '0px'
              },
              widgetConfig: {

              }
            }
          }
        }
      // }

      // console.log(widgetConfigProps)
      let computed = {
        srules: `A.getRulesFromRulesArr(MODEL('rulesArr'))`,
        get_computedFunIns: `A.get_computedFunIns(MODEL('computedFunIns'))`,
        ui_css: `A.getui_css(MODEL('css'))`,
        ...widgetComputedProps,
      }
      let formDef = {
        type: 'object',

        tag: 'xy-tab',
        ui: {
          attrs: [
            ['label-width', '90px']
          ],
        },
        properties,
      }
      let _cached = DRAG_INSTANSE.getConfig(treeState.current.uuid)
      let defaultVal = setPROPS({
        ui: {
          widgetConfig: {
          }
        },
        server: {
        }
      }, _cached?.ins ?? {})
      // console.log('defaultVal',  _cached?.ins, defaultVal)
      return {
        default: createCusWidgetEditorConfig(formDef,
            computed,
            defaultVal
        )
      }
    }

    // widget锁
    let widgetFormLocks = false

    /**
     * 当model改变时
     * @param e
     */
    function onModelChange(e) {
      let model = e.model ?? {}
      if (widgetFormLocks) {
      //
      } else {
        // console.log(model, treeState.current.ext)
        DRAG_INSTANSE.setConfig(treeState.current.uuid, {
          ins: model,
          common: treeState.current.ext
        })
        // console.log(model)
      }
    }

    function get_current_config(path, defaultVal) {
      let config = DRAG_INSTANSE.getConfig(treeState.current.uuid)
      let o = config ?? {}
      return ZY.deepGet(o, path, defaultVal)
    }

    let _initTreeRef = null
    function initTreeRef(el) {
      _initTreeRef = el
    }

    function selectTree() {
      // let current = _initTreeRef.getCurrentNode()
      // console.log(treeState.data)
      // let tree_id = treeState.data[0].tree_id
      // console.log(tree_id, treeState.data)
      // _initTreeRef.setCurrentKey(tree_id)
    }


    function onSelectList(e) {
      let uuid = treeState?.current?.uuid ?? ''
      if (uuid) {
        let context = DRAG_INSTANSE.getRegisterCtx(uuid)
        // console.log(context)
        context.setVal(e.origin.value)
      }
    }

    function onSelectChecked(e) {
      let uuid = treeState?.current?.uuid ?? ''
      if (uuid) {
        let context = DRAG_INSTANSE.getRegisterCtx(uuid)
        // console.log('onSelectList', e)
        let arr = e.origin.options ?? []
        if (Array.isArray(arr)) {
          arr = arr.map(v => v.value)
        }
        context.setVal(arr)
        // console.log('onSelectChecked', arr)
      }
    }

    /**
     * 获取存储
     * @returns {{defs: {}, state: {layouts: *[], uuids: *[]}}}
     */
    function getMemo() {
      let ret = {
        state: {
          layouts: toRaw(state.layouts),
          uuids:  toRaw(state.uuids),
        },
        defs: {},
      }
      ret.treeState ={
        data: toRaw(treeState.data)
      }
      ret.dragConfig =  JSON5.stringify(
          [...toRaw(treeState.dragConfig)]
      )
      lodash.each(state.layoutRefMap, function (map, key) {
        ret.defs[key] = map.el.toMemo()
      })

      // console.log(memos)
      ret.memoDatas = []
      memos.forEach(function (item, key) {
        if (item && item.toMemo) {
          let _memo = item.toMemo()
          ret.memoDatas.push([
              key,
              _memo
          ])
        }
      })
      // console.log( ret.memos)

      // 处理元素toMemo
      ret.comMemo = {
      }
      let dragContextMap = DRAG_INSTANSE.getCtxs()
      // console.log(dragContextMap)
      dragContextMap.forEach( function (item, key) {
        // console.log(item, key)
        if (item.toMemo) {
          ret.comMemo[key] = item.toMemo()
        }
      })

      // console.log(ret.comMemo )
      return ret
    }

    /**
     * 导入数据
     * @param obj_data
     */
    function importData(obj_data = {}) {
      ZY.lodash.each(obj_data.state, function (item, key) {
        // console.log(item, key)
        state[key] = item
      })
      ZY.lodash.each(obj_data.treeState, function (item, key) {
        // console.log(item, key)
        treeState[key] = item
      })
      // ZY.lodash.each(obj_data.memoDatas, function (item, key) {
      //   console.log(item, key)
      //
      // })
      if (obj_data.memoDatas) {
        // memoDatas = new Map(obj_data.memoDatas)
        // console.log(obj_data.memoDatas)
        obj_data.memoDatas.forEach(function ([key, item]) {
          memoDatas.set(key, item)
        })
        // console.log(memoDatas)
      }
      state.comMemo = obj_data.comMemo
      nextTick(() => {
        lodash.each(obj_data.defs, (item, uuid) => {
          let map = state.layoutRefMap[uuid]
          // console.log(item, map)
          if (map && map.el) {
            map.el.fromMemo(item)
          }
        })
        try {
          if (obj_data.dragConfig) {
            let map = new Map(JSON5.parse(obj_data.dragConfig))

            console.log(map)
            map.forEach((item, key) => {
              DRAG_INSTANSE.setConfig(key, item)
            })

            // DRAG_INSTANSE.getAllConfig().forEach(function (item, key) {
            //   console.log(key)
            //   DRAG_INSTANSE.delConfig(key)
            //
            // })
            //
            // console.log(DRAG_INSTANSE.getAllConfig())

          }
        } catch (e) {
          console.log(e, obj_data)
        }

        // let ctx = DRAG_INSTANSE.getCtxs()
        // console.log(ctx)
        // ctx.forEach( function (item, key) {
        //   // console.log(item, key)
        //   if (item.fromMemo) {
        //     item.fromMemo(obj_data.comMemo)
        //   }
        // })
        rebuildSortable()
      })
    }

    async function exportFile({form}) {
      // console.log(form)
      let m = getMemo()
      let fileName = 'dragxml_export'
      if (form.fileName) {
        fileName = form.fileName
      }
      // console.log(DRAG_INSTANSE.dragConfig)
      // await ZY_EXT.store.setItem('test_export', ZY.JSON5.stringify( { data: m }) )
      ZY_EXT.saveDesignFile({fileName, data: m})
    }

     async function importFile() {
       let obj = await ZY_EXT.fileOpenJSON5()
       // let data = await ZY_EXT.store.getItem('test_export') ?? '{}'
       // let obj = ZY.JSON5.parse(data)
       if (obj.data) {
         const obj_data = obj.data
         // console.log(obj)
         importData(obj_data)
       }
     }

    onMounted(() => {
      const mo = new MutationObserver(onMutation);
      mo.observe(getPlaygroundDOM(), {
        attributes : true,
        subtree: true,
        childList: true
      });

      let cusDragXml = inject('cusDragXml');
      if (cusDragXml && cusDragXml.onZDragxmlReady) {
        cusDragXml.onZDragxmlReady()
      }
    })

    function onSetFormConfig(newVal) {
      emitter.emit(DRAG_EVENTS.FORM_CONFIG, newVal)
    }

    /**
     *
     * @param element
     * @returns {boolean}
     */
    function checkIsShowMenuItem(element) {
      // console.log('element', element, __USE_EXP__)
      if (typeof element.exp === 'undefined') {
        return true
      } else {
        if (__USE_EXP__) {
          // console.log(__USE_EXP__, element.exp)
          return __USE_EXP__ === ( element.exp + '')
        }
        return false
      }
    }

    // 检测是否操作过
    let isClicked = false
    function onMouseLeave(e) {
      let instance = document.getElementById(ELE_ID)
      let rect = instance.getBoundingClientRect()
      // console.log('onMouseLeave', e, rect)
      if (e.pageY < rect.y) {
        if (isClicked) {
          isClicked = false
          ctx.emit('editor-leave', {origin: e})
        }
      }

    }



    function onMouseDown(e) {
      if (e.pageY > bindingRect.y + 60) {
        isClicked  = true
      }
    }

    function getTreeStateCurrentCls() {
      // console.log(treeState.current)
      let com = treeState?.current?.origin?.com
      if (com) {
        return com.DRAG_PANEL_CLS ?? ''
      }
      return ''
    }

    /**
     * 导出的ctx
     * @type {{}}
     */
    let exportCtx = {
      tplManager,
      clearOldData() {
        DRAG_INSTANSE.clearAllCtx()
        DRAG_INSTANSE.clearAllConfig()
      },
      importFromTplStr(obj_str = '{}') {
        let objData = ZY.JSON5.parse(obj_str);
        if (objData && objData.data) {
          importData(objData.data)
        }
      },
      getExportData() {
        return {
          data:  getMemo()
        }
      },
      getZProps
    }

    return {
      list1ItemCls,
      selectTree,
      initTreeRef,
      state,
      getRef,
      tplManager,
      // getTplComponents,
      onSetFormConfig,
      playgroundId: PLAY_ID,
      onDropStart,
      ELE_ID,
      importData,
      exportCtx,
      exportFile,
      importFile,
      downloadJSON,
      initZlayoutInitRef,
      onDragMove,
      onMouseLeave,
      onMouseDown,
      onZLayoutInitDragEnter,
      onChangedLayout,
      onDragEnd,
      onClearIndex,
      getMemo,
      testId1: TEST1_ID,
      testId2: TEST2_ID,
      testId3: TEST3_ID,
      TEST_IDS,
      checkIsShowMenuItem,
      onSelectList,
      onSelectChecked,
      onDropEnd,
      onMouseMove,
      treeState,
      getZProps,
      initScrollRef,
      removeTreeNode,
      toolState,
      toggleShowMenu,
      handleMenuSelect,
      handleMenuClose,
      getTreeStateCurrentCls,
      resolveConfig,
      get_current_config,
      onModelChange,
      // onMouseLeave,
      handleTreeNodeClick,
    }
  }
}
</script>
